import 'package:flutter/material.dart';
import 'package:fluttercommon/src/http/http_wrapper.dart';

import '../extentions/string_extentions.dart';

typedef Future<ApiResult> SmsMessenger(String mobile);

class SendSmsWidget extends StatefulWidget {
  final ValueNotifier<String> mobileNotifier;
  final SmsMessenger smsMessenger;
  final ValueChanged<String?>? onSendSmsFailed;
  final bool hasStadiumBackground;
  final TextStyle? style;
  final TextStyle? disabledStyle;
  final double fontSize;
  final double height;
  final VoidCallback? onSendSmsSuccess;
  final String sendSmsCodeLabel;

  const SendSmsWidget({
    Key? key,
    required this.mobileNotifier,
    required this.smsMessenger,
    this.onSendSmsFailed,
    this.hasStadiumBackground = true,
    this.style,
    this.disabledStyle,
    this.fontSize = 14,
    this.height = 30,
    this.onSendSmsSuccess,
    this.sendSmsCodeLabel = "获取验证码",
  }) : super(key: key);

  @override
  _SendSmsWidgetState createState() => _SendSmsWidgetState();
}

class _SendSmsWidgetState extends State<SendSmsWidget> {
  bool hasSentSms = false;
  final smsWaitSeconds = 60;
  int counter = 0;
  bool sendingSmsCode = false;

  String get mobile => widget.mobileNotifier.value;

  bool get canSendSmsCode => mobile.isMobile() && !sendingSmsCode;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    counter = 0;
    sendingSmsCode = false;
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: widget.height,
      child: ValueListenableBuilder(
        valueListenable: widget.mobileNotifier,
        builder: (BuildContext context, String value, Widget? child) {
          final theme = Theme.of(context);
          final style = canSendSmsCode
              ? (widget.style ??
                  TextStyle(
                    fontSize: widget.fontSize,
                    color: (widget.hasStadiumBackground == true
                        ? Colors.white
                        : theme.primaryColor),
                  ))
              : (widget.disabledStyle ??
                  TextStyle(
                    fontSize: widget.fontSize,
                    color: Colors.grey,
                  ));
          final color = canSendSmsCode ? theme.primaryColor : Colors.grey;
          final onPressed = canSendSmsCode ? sendSmsCode : null;
          final text = sendingSmsCode
              ? "${widget.sendSmsCodeLabel}(${counter}s)"
              : "${widget.sendSmsCodeLabel}";
          if (widget.hasStadiumBackground == true) {
            return ElevatedButton(
              child: Text(
                text,
                style: style,
                strutStyle: StrutStyle(forceStrutHeight: true),
              ),
              style: ElevatedButton.styleFrom(
                primary: color,
                shape: StadiumBorder(),
                padding: EdgeInsets.symmetric(horizontal: 12.0),
              ),
              onPressed: onPressed,
            );
          } else {
            return TextButton(
              child: Text(
                text,
                style: style,
                strutStyle: StrutStyle(forceStrutHeight: true),
              ),
              onPressed: onPressed,
            );
          }
        },
      ),
    );
  }

  void sendSmsCode() {
    if (sendingSmsCode) {
      print("ignore duplicated events.");
      return;
    }
    setState(() {
      sendingSmsCode = true;
    });
    widget.smsMessenger(mobile).then((result) {
      if (result.success()) {
        updateTimer();
        if (widget.onSendSmsSuccess != null) {
          widget.onSendSmsSuccess!();
        }
      } else {
        widget.onSendSmsFailed?.call(result.message());
        setState(() {
          sendingSmsCode = false;
        });
      }
    });
  }

  Future updateTimer() async {
    counter = smsWaitSeconds;
    if (mounted) {
      setState(() {
        sendingSmsCode = true;
      });
    }
    Future.doWhile(() async {
      await Future.delayed(Duration(seconds: 1));
      counter--;
      if (mounted) {
        setState(() {});
      }
      debugPrint("counter: $counter");
      return counter > 0 && mounted;
    }).whenComplete(() {
      counter = 0;
      sendingSmsCode = false;
      if (mounted) {
        setState(() {});
      }
    });
  }
}
